/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "MultiFile_iPhone.h"
#include "File.h"
#include "Memory.h"
#include <NoCopy.h>
#include <filesystem/File.h>
#include <logs/Log.h>
#include <memory>
#include <Gluck.h>
#include <vector>
#include <system/Environment.h>
#include <sys/sysctl.h>  
#include <mach/mach.h>
#include <CoreFoundation/CFLocale.h>
#include <CoreFoundation/CFString.h>

extern bool isPad();
static double availableMemoryIOS()
{
	vm_statistics_data_t vmStats;
	mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
	kern_return_t kernReturn = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount);
	
	if(kernReturn != KERN_SUCCESS) {
		return -1;
	}
	
	return ((vm_page_size * vmStats.free_count) / 1024.0) / 1024.0;
}

namespace liba
{
namespace resource
{

MultiFile::MultiFile(const std::string & filename) : archive(NULL)
{
	std::string fullPath = (filesystem::String("%app_path%/").c_str() + filesystem::String(filename)).c_str();
	archive = zip_open(fullPath.c_str(), 0, NULL);
}
	
MultiFile::~MultiFile()
{
}

Resource * MultiFile::create_resource(const filesystem::String & fname)
{
	if(!archive)
		return NULL;
	
	CFLocaleRef locale = CFLocaleCopyCurrent();
	CFStringRef locale_id = CFLocaleGetIdentifier(locale);
	
	char buffer[1024];
	CFStringGetCString( locale_id, buffer, 1024, CFStringGetSystemEncoding() );
	std::string locale_string = buffer;
	filesystem::String multilanguage_name = fname;
	
	std::string str_to_lower;
	const char * buff = fname.c_str();
	for( unsigned i = 0; i < fname.size(); ++i )
	{
		str_to_lower += tolower(buff[i]);
	}
	
	resource::Resource * res = 0;

	if(availableMemoryIOS() > 50)
	{
		//we are >= 3GS or iPad, try hd resource
		filesystem::String multilanguage_name = "hd/" + str_to_lower;
		
		//try localized resource hd
		filesystem::String localized_str = "hd/" + locale_string + "/" + str_to_lower;

		res = create_resource_from_file( localized_str );
		if( res )
			return res;
		
		res = create_resource_from_file( multilanguage_name );
		if( res )
			return res;
	}

	if(isPad())
	{
		filesystem::String localized_str = "ipad/" + locale_string + "/" + str_to_lower;
		
		res = create_resource_from_file( localized_str );
		if( res )
			return res;

		multilanguage_name = "ipad/" + str_to_lower;
		
		res = create_resource_from_file( multilanguage_name );
		if( res )
			return res;
		
	}
	
	filesystem::String localized_str = locale_string + "/" + str_to_lower;

	res = create_resource_from_file( localized_str );
	if( res )
		return res;
	
	//otherwise try to create directly
	return create_resource_from_file( fname );
}
	
	
Resource * MultiFile::create_resource_from_file(const filesystem::String & name)
{
	std::string fileName = name.c_str();

	if(fileName[0] == '/')
		fileName = fileName.substr(1);
	
	struct zip_stat stat;
	zip_stat_init(&stat);

	if(zip_stat(archive, fileName.c_str(), ZIP_FL_UNCHANGED, &stat))
		return 0;
	
	zip_file* file = zip_fopen(archive, fileName.c_str(), 0);
	if (!file)
		return 0;
	
	std::vector<char> data;
	data.resize(stat.size);
	
	zip_fread(file, &(data.front()), stat.size);
	zip_fclose(file); file = 0;
	
	resource::Memory * res = new resource::Memory(data);	
	return res;
}

} // namespace resource
} // namespace liba

